home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
001-025
/
002
/
make
/
lar.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-13
|
17KB
|
743 lines
/*
* Lar - LAR format library file maintainer
* by Stephen C. Hemminger
* linus!sch or sch@Mitre-Bedford
*
* Heavily hacked for MS-DOS by Eric C. Brown
* utah-cs!brownc or brownc@utah-cs
*
* Usage: lar key library [files] ...
*
* Key functions are:
* u - Update, add files to library
* t - Table of contents
* e - Extract files from library
* a - extract All files from library
* p - Print files in library
* d - Delete files in library
* r - Reorganize library
* Other keys:
* v - Verbose
*
* This program is public domain software, no warranty intended or
* implied.
*
* DESCRPTION
* Lar is a MS-DOS program to manipulate program libraries.
* The primary use of lar is to combine several files together
* to reduce disk space used.
* Lar maintains the date and time of files in the library, so
* that Make can extract the date/time for rebuilding a file.
* When files are restored, the file has the original date/time
* rather than the date/time when the file was extracted.
* The original CP/M library program LU is the product
* of Gary P. Novosielski.
*
* PORTABILITY
* The code is modeled after the Software tools archive program,
* and is setup for Version 7 Unix. It does not make any assumptions
* about byte ordering, explict and's and shift's are used.
* If you have a dumber C compiler, you may have to recode new features
* like structure assignment, typedef's and enumerated types.
*
* * Unix is a trademark of Bell Labs.
* ** CP/M is a trademark of Digital Research.
*/
#include "lar.h"
/* Globals */
char *fname[MAXFILES];
bool ftouched[MAXFILES];
struct ludir ldir[MAXFILES];
int errcnt, nfiles, nslots;
bool verbose = false;
char *getname(), *malloc(), *fgets();
long fcopy(), lseek(), rlwtol();
int update(), reorg(), table(), extract(), print(), delete(), getall();
typedef int (*PFI)();
main (argc, argv)
int argc;
char **argv;
{
register char *flagp;
char *aname; /* name of library file */
PFI function = (PFI) NULL; /* function to do on library */
/* set the function to be performed, but detect conflicts */
#define setfunc(val) if(function != (PFI) NULL) conflict(); else function = val
if (argc < 3)
help ();
aname = argv[2];
filenames (argc, argv);
for(flagp = argv[1]; *flagp; flagp++)
switch (*flagp) {
case 'u':
setfunc(update);
break;
case 't':
setfunc(table);
break;
case 'e':
setfunc(extract);
break;
case 'a':
setfunc(getall);
break;
case 'p':
setfunc(print);
break;
case 'd':
setfunc(delete);
break;
case 'r':
setfunc(reorg);
break;
case 'v':
verbose = true;
break;
default:
help ();
}
if(function == (PFI) NULL) {
fputs("No function key letter specified\n", stderr);
help();
}
(*function)(aname);
exit(0);
}
/* print error message and exit */
help () {
fputs ("Usage: lar {uteapdr}[v] library [files] ...\n", stderr);
fputs ("Functions are:\n\tu - Update, add files to library\n", stderr);
fputs ("\tt - Table of contents\n", stderr);
fputs ("\te - Extract files from library\n", stderr);
fputs ("\ta - extract All files from library\n", stderr);
fputs ("\tp - Print files in library\n", stderr);
fputs ("\td - Delete files in library\n", stderr);
fputs ("\tr - Reorganize library\n", stderr);
fputs ("Flags are:\n\tv - Verbose\n", stderr);
exit (1);
}
conflict() {
fputs ("Conficting keys\n", stderr);
help();
}
/*
* This ltoa doesn't call in the floating point library:
* CI C86 does an sprintf!
*/
ltoa(val, buf)
long val;
register char *buf;
{
register int i;
int j;
char tbuf[20];
if (val == 0) {
buf[0] = '0';
buf[1] = '\0';
return;
}
i = 19;
while (val != 0) {
tbuf[i--] = (val % 10) + '0';
val /= 10;
}
i++;
for (j = 0; i <= 19; i++, j++)
buf[j] = tbuf[i];
buf[j] = '\0';
}
/* Get file names, check for dups, and initialize */
filenames (ac, av)
int ac;
char **av;
{
register int i, j=0;
int k, loop;
struct ffblk ff;
bool iswild();
errcnt = 0;
for (i = 0; i < ac - 3; i++) {
if (iswild(av[i + 3])) {
k = findfirst(av[i + 3], &ff, 0);
while (k == 0) {
fname[j] = malloc(strlen(ff.ff_name)+1);
if (fname[j] == NULL)
error("Out of core..");
strcpy(fname[j], ff.ff_name);
for (loop = 0; ff.ff_name[loop] != 0; loop++)
fname[j][loop] = tolower(ff.ff_name[loop]);
ftouched[j] = false;
if (j == MAXFILES)
error ("Too many file names.");
j++;
k = findnext(&ff);
} /* while */
} /* if-then */
else { /* not a wildcard */
fname[j] = av[i+3];
ftouched[j] = false;
if (j == MAXFILES)
error ("Too many file names.");
j++;
} /* else */
} /* for */
checkdups(j);
}
bool iswild(str)
register char *str;
{
while (*str != '\0') {
if (*str == '*' || *str == '?')
return true;
else str++;
}
return false;
}
checkdups(i)
register int i;
{
register int j;
fname[i] = NULL;
nfiles = i;
for (i = 0; i < nfiles; i++)
for (j = i + 1; j < nfiles; j++)
if (equal (fname[i], fname[j])) {
fputs (fname[i], stderr);
error (": duplicate file name");
}
}
table (lib)
char *lib;
{
fildesc lfd;
register int i;
register struct ludir *lptr;
long total, offset, size;
int active = 0, unused = 0, deleted = 0, k;
char *uname, buf[20];
if ((lfd = _open (lib, O_RDWR)) == SYS_ERROR)
cant (lib);
getdir (lfd);
total = lwtol(ldir[0].l_len);
if (verbose) {
puts("Name Index Length");
fputs("Directory ", stdout);
ltoa(total, buf);
puts(buf);
}
for (i = 1, lptr = &ldir[1]; i < nslots; i++,lptr++)
switch(lptr->l_stat) {
case ACTIVE:
active++;
uname = getname(lptr->l_name, lptr->l_ext);
if (filarg (uname))
if(verbose) {
offset = lwtol(lptr->l_off);
size = lwtol(lptr->l_len);
fputs(uname, stdout);
for (k = 1; k < 18 - strlen(uname); k++)
fputc(' ', stdout);
ltoa(offset, buf);
fputs(buf, stdout);
for (k = 1; k < 16 - strlen(buf); k++)
fputc(' ', stdout);
ltoa(size, buf);
puts(buf, stdout);
}
else
puts(uname);
total += lwtol(lptr->l_len);
break;
case UNUSED:
unused++;
break;
default:
deleted++;
}
if(verbose) {
puts("--------------------------------------");
fputs("Total bytes ", stdout);
ltoa(total, buf);
puts(buf);
fputs("\nLibrary ", stdout);
fputs(lib, stdout);
fputs(" has ", stdout);
itoa(nslots, buf);
fputs(buf, stdout);
fputs(" slots, ", stdout);
itoa(deleted, buf);
fputs(buf, stdout);
fputs(" deleted ", stdout);
itoa(active, buf);
fputs(buf, stdout);
fputs(" active, ", stdout);
itoa(unused, buf);
fputs(buf, stdout);
puts(" unused");
}
VOID _close (lfd);
not_found ();
}
putdir (f)
fildesc f;
{
lseek(f, 0L, 0); /* rewind f */
if (_write (f, (char *) ldir, DSIZE * nslots) != nslots * DSIZE)
error ("Can't write directory - library may be botched");
}
initdir (f)
fildesc f;
{
register int i;
long numbytes;
char line[80];
static struct ludir blankentry = {
UNUSED,
{ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
{ ' ', ' ', ' ' },
};
static struct ludir nameentry = {
ACTIVE,
{ 'l', 'a', 'r', 'f', 'o', 'r', 'm', 't' },
{ 'a', 'r', 'c' },
};
for (;;) {
fputs ("Number of slots to allocate (1-255): ", stdout);
if (fgets (line, 80, stdin) == NULL)
error ("Eof when reading input");
nslots = atoi (line);
if (nslots < 1)
puts ("Must have at least one!");
else if (nslots > MAXFILES)
puts ("Too many slots");
else
break;
}
numbytes = nslots * DSIZE;
for (i = 1; i < nslots; i++)
ldir[i] = blankentry;
ldir[0] = nameentry;
ltolw (ldir[0].l_len, numbytes);
ltolw (ldir[0].l_datetime, -1L); /* make funny date field */
putdir (f);
}
putname (cpmname, unixname)
char *cpmname, *unixname;
{
register char *p1, *p2;
for (p1 = unixname, p2 = cpmname; *p1; p1++, p2++) {
while (*p1 == '.') {
p2 = cpmname + 8;
p1++;
}
if (p2 - cpmname < 11)
*p2 = islower(*p1) ? toupper(*p1) : *p1;
else {
fputs (unixname, stderr);
fputs (": name truncated\n", stderr);
break;
}
}
while (p2 - cpmname < 11)
*p2++ = ' ';
}
/* filarg - check if name matches argument list */
filarg (name)
char *name;
{
register int i;
if (nfiles <= 0)
return 1;
for (i = 0; i < nfiles; i++)
if (equal (name, fname[i])) {
ftouched[i] = true;
return 1;
}
return 0;
}
not_found () {
register int i;
for (i = 0; i < nfiles; i++)
if (!ftouched[i]) {
fputs(fname[i], stderr);
fputs(": not in library.\n", stderr);
errcnt++;
}
}
extract(name)
char *name;
{
getfiles(name, false);
}
print(name)
char *name;
{
getfiles(name, true);
}
getall (libname)
char *libname;
{
fildesc lfd, ofd;
register int i;
register struct ludir *lptr;
union timer timeunion;
extern int errno;
char *unixname;
if ((lfd = _open (libname, O_RDWR)) == SYS_ERROR)
cant (libname);
getdir (lfd);
for (i = 1, lptr = &ldir[1]; i < nslots; i++, lptr++) {
if(lptr->l_stat != ACTIVE)
continue;
unixname = getname (lptr->l_name, lptr->l_ext);
fputs(unixname, stderr);
ofd = _creat(unixname, 0);
if (ofd == SYS_ERROR) {
fputs (" - can't create", stderr);
errcnt++;
}
else {
VOID lseek (lfd, (long) lwtol (lptr->l_off), 0);
acopy (lfd, ofd, lwtol (lptr->l_len));
timeunion.realtime = lwtol(lptr->l_datetime);
VOID setftime(ofd, &(timeunion.ftimep));
VOID _close (ofd);
}
putc('\n', stderr);
}
VOID _close (lfd);
not_found ();
}
getfiles (name, pflag)
char *name;
bool pflag;
{
fildesc lfd, ofd;
register int i;
register struct ludir *lptr;
union timer timeunion;
extern int errno;
char *unixname;
if ((lfd = _open (name, O_RDWR)) == SYS_ERROR)
cant (name);
ofd = pflag ? fileno(stdout) : SYS_ERROR;
getdir (lfd);
for (i = 1, lptr = &ldir[1]; i < nslots; i++, lptr++) {
if(lptr->l_stat != ACTIVE)
continue;
unixname = getname (lptr->l_name, lptr->l_ext);
if (!filarg (unixname))
continue;
fputs(unixname, stderr);
if (ofd != fileno(stdout))
ofd = _creat(unixname, 0);
if (ofd == SYS_ERROR) {
fputs (" - can't create", stderr);
errcnt++;
}
else {
VOID lseek (lfd, (long) lwtol (lptr->l_off), 0);
acopy (lfd, ofd, lwtol (lptr->l_len));
timeunion.realtime = lwtol(lptr->l_datetime);
if (ofd != fileno(stdout)) {
VOID setftime(ofd, &(timeunion.ftimep));
VOID _close (ofd);
}
}
putc('\n', stderr);
}
VOID _close (lfd);
not_found ();
}
acopy (fdi, fdo, nbytes) /* copy nbytes from fdi to fdo */
fildesc fdi, fdo;
long nbytes;
{
register int btr, retval;
char blockbuf[BLOCK];
for (btr = (nbytes > BLOCK) ? BLOCK : (int) nbytes; btr > 0;
nbytes -= BLOCK, btr = (nbytes > BLOCK) ? BLOCK : (int) nbytes) {
if ((retval = _read(fdi, blockbuf, btr)) != btr) {
if( retval == 0 ) {
error("Premature EOF\n");
}
if( retval == SYS_ERROR)
error ("Can't read");
}
if ((retval = _write(fdo, blockbuf, btr)) != btr) {
if( retval == SYS_ERROR )
error ("Write Error");
}
}
}
update (name)
char *name;
{
fildesc lfd;
register int i;
if ((lfd = _open(name, O_RDWR)) == SYS_ERROR) {
if ((lfd = _creat (name, 0)) == SYS_ERROR) {
cant (name);
}
else
initdir (lfd);
}
else
getdir (lfd); /* read old directory */
if(verbose)
fputs ("Updating files:\n", stderr);
for (i = 0; i < nfiles; i++)
addfil (fname[i], lfd);
if (errcnt == 0)
putdir (lfd);
else
fputs("fatal errors - library not changed\n", stderr);
VOID _close (lfd);
}
addfil (name, lfd)
char *name;
fildesc lfd;
{
fildesc ifd;
register int i;
register struct ludir *lptr;
long byteoffs, numbytes;
union timer timeunion;
if ((ifd = _open(name, O_RDWR)) == SYS_ERROR) {
fputs("LAR: can't find ", stderr);
fputs(name, stderr);
fputs(" to add\n", stderr);
errcnt++;
return;
}
if(verbose) {
fputs(name, stderr);
fputs("\n", stderr);
}
for (i = 1, lptr = ldir+1; i < nslots; i++, lptr++) {
if (equal( getname (lptr->l_name, lptr->l_ext), name) ) /* update */
break;
if (lptr->l_stat != ACTIVE)
break;
}
if (i >= nslots) {
fputs(name, stderr);
fputs(": can't add library is full\n",stderr);
errcnt++;
return;
}
lptr->l_stat = ACTIVE;
putname (lptr->l_name, name);
byteoffs = lseek(lfd, 0L, 2); /* append to end; return byte offset */
ltolw (lptr->l_off, byteoffs);
numbytes = fcopy (ifd, lfd);
ltolw (lptr->l_len, numbytes);
getftime(ifd, &(timeunion.ftimep));
ltolw (lptr->l_datetime, timeunion.realtime);
VOID _close (ifd);
}
long fcopy (ifd, ofd) /* copy file ifd (file) to ofd (library) */
fildesc ifd, ofd;
{
long total = 0L;
register int n;
char blockbuf[BLOCK];
while ( (n = _read(ifd, blockbuf, BLOCK)) > 0) {
if (_write(ofd, blockbuf, n) != n)
error("write error");
total += (long) n;
}
return total;
}
delete (lname)
char *lname;
{
fildesc f;
register int i;
register struct ludir *lptr;
if ((f = _open(lname, O_RDWR)) == SYS_ERROR)
cant (lname);
if (nfiles <= 0)
error("delete by name only");
getdir (f);
for (i = 0, lptr = ldir; i < nslots; i++, lptr++) {
if (!filarg ( getname (lptr->l_name, lptr->l_ext)))
continue;
lptr->l_stat = DELETED;
}
not_found();
if (errcnt > 0)
fputs ("errors - library not updated\n", stderr);
else
putdir (f);
VOID _close (f);
}
reorg (name)
char *name;
{
fildesc olib, nlib;
int oldsize, k;
register struct ludir *optr;
register int i, j;
struct ludir odir[MAXFILES], *nptr;
char tmpname[80], buf[10];
char *mktemp();
strcpy(tmpname, mktemp("libXXXXXX"));
if( (olib = _open(name, O_RDWR)) == SYS_ERROR)
cant(name);
if( (nlib = _creat(tmpname, 0)) == SYS_ERROR)
cant(tmpname);
getdir(olib);
fputs("Old library has ", stdout);
itoa(oldsize = nslots, buf);
fputs(buf, stdout);
puts(" slots.");
/* copy ldir into odir */
for(i = 0, optr = ldir, nptr = odir ; i < nslots ; i++, optr++, nptr++)
movmem((char *) optr, (char *) nptr, sizeof(struct ludir));
/* reinit ldir */
initdir(nlib);
errcnt = 0;
/* copy odir's files into ldir */
for (i = j = 1, optr = odir+1; i < oldsize; i++, optr++) {
if( optr->l_stat == ACTIVE ) {
if(verbose) {
fputs("Copying: ", stderr);
for (k = 0; k < 8; k++)
fputc(optr->l_name[k], stderr);
fputc('.', stderr);
for (k = 0; k < 3; k++)
fputc(optr->l_ext[k], stderr);
fputc('\n', stderr);
}
copyentry( optr, olib, &ldir[j], nlib);
if (++j >= nslots) {
errcnt++;
fputs("Not enough room in new library\n", stderr);
break;
}
}
}
VOID _close(olib);
putdir(nlib);
VOID _close (nlib);
if(errcnt == 0) {
if (unlink(name) < 0 || rename(tmpname, name) < 0) {
cant(name);
exit(1);
}
}
else
fputs("Errors, library not updated\n", stderr);
VOID unlink(tmpname);
}
copyentry( old, of, new, nf )
struct ludir *old, *new;
fildesc of, nf;
{
long byteoffs, numbytes;
register int btr;
char blockbuf[BLOCK];
new->l_stat = ACTIVE;
movmem(old->l_name, new->l_name, 8); /* copy name */
movmem(old->l_ext, new->l_ext, 3); /* copy extension */
numbytes = lwtol(old->l_datetime); /* copy date & time */
ltolw(new->l_datetime, numbytes);
VOID lseek(of, (long) lwtol(old->l_off), 0);
byteoffs = lseek(nf, 0L, 2); /* append to end; return new pos. */
ltolw (new->l_off, byteoffs);
numbytes = lwtol(old->l_len);
ltolw (new->l_len, numbytes);
for (btr = (numbytes > BLOCK) ? BLOCK : (int) numbytes; btr > 0;
numbytes -= BLOCK, btr = (numbytes > BLOCK) ? BLOCK : (int) numbytes
) {
if (_read(of, blockbuf, btr) != btr) {
error ("Read Error in CopyEntry");
}
if (_write(nf, blockbuf, btr) != btr) {
error ("Write Error in CopyEntry");
}
}
}